package com.xujie.sportsmeeting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.sportsmeeting.dto.EventCheckinDTO;
import com.xujie.sportsmeeting.entity.Athlete;
import com.xujie.sportsmeeting.entity.CompetitionEvent;
import com.xujie.sportsmeeting.entity.EventCheckin;
import com.xujie.sportsmeeting.entity.Registration;
import com.xujie.sportsmeeting.entity.EventRegistration;
import com.xujie.sportsmeeting.mapper.EventCheckinMapper;
import com.xujie.sportsmeeting.service.AthleteService;
import com.xujie.sportsmeeting.service.CompetitionEventService;
import com.xujie.sportsmeeting.service.EventCheckinService;
import com.xujie.sportsmeeting.service.RegistrationService;
import com.xujie.sportsmeeting.service.EventRegistrationService;
import com.xujie.sportsmeeting.vo.EventCheckinVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 赛事检录服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EventCheckinServiceImpl extends ServiceImpl<EventCheckinMapper, EventCheckin> 
        implements EventCheckinService {

    private final RegistrationService registrationService;
    private final EventRegistrationService eventRegistrationService;
    private final AthleteService athleteService;
    private final CompetitionEventService competitionEventService;

    @Override
    public IPage<EventCheckinVO> getCheckinPage(Page<EventCheckinVO> page, 
                                              Long eventId, 
                                              String athleteName, 
                                              String studentNumber, 
                                              String department, 
                                              Integer checkinStatus) {
        // 使用MyBatis-Plus查询检录记录
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        
        if (eventId != null) {
            wrapper.eq(EventCheckin::getEventId, eventId);
        }
        if (athleteName != null && !athleteName.trim().isEmpty()) {
            wrapper.like(EventCheckin::getAthleteName, athleteName.trim());
        }
        if (studentNumber != null && !studentNumber.trim().isEmpty()) {
            wrapper.like(EventCheckin::getStudentNumber, studentNumber.trim());
        }
        if (checkinStatus != null) {
            wrapper.eq(EventCheckin::getCheckinStatus, checkinStatus);
        }
        
        wrapper.orderByDesc(EventCheckin::getCreateTime);
        
        Page<EventCheckin> checkinPage = this.page(new Page<>(page.getCurrent(), page.getSize()), wrapper);
        
        // 转换为VO
        IPage<EventCheckinVO> voPage = new Page<>(checkinPage.getCurrent(), checkinPage.getSize(), checkinPage.getTotal());
        List<EventCheckinVO> voList = checkinPage.getRecords().stream().map(this::convertToVO).toList();
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    public List<EventCheckinVO> getCheckinByEventId(Long eventId) {
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventCheckin::getEventId, eventId)
               .orderBy(true, true, EventCheckin::getRaceNumber, EventCheckin::getStudentNumber);
        
        List<EventCheckin> checkinList = this.list(wrapper);
        return checkinList.stream().map(this::convertToVO).toList();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createCheckinRecords(Long eventId) {
        try {
            log.info("开始为项目 {} 创建检录记录", eventId);
            
            // 1. 查询该项目已通过审核的报名记录
            LambdaQueryWrapper<EventRegistration> registrationWrapper = new LambdaQueryWrapper<>();
            registrationWrapper.eq(EventRegistration::getEventId, eventId)
                              .eq(EventRegistration::getAuditStatus, 1)  // 审核通过
                              .eq(EventRegistration::getStatus, 1);     // 正常状态
            
            List<EventRegistration> registrations = eventRegistrationService.list(registrationWrapper);
            log.info("查询到项目 {} 的报名记录数量: {}", eventId, registrations.size());
            
            if (registrations.isEmpty()) {
                log.warn("项目 {} 没有已审核通过的报名记录", eventId);
                // 查询该项目的所有报名记录，用于调试
                LambdaQueryWrapper<EventRegistration> allWrapper = new LambdaQueryWrapper<>();
                allWrapper.eq(EventRegistration::getEventId, eventId);
                List<EventRegistration> allRegistrations = eventRegistrationService.list(allWrapper);
                log.info("项目 {} 的所有报名记录数量: {}", eventId, allRegistrations.size());
                for (EventRegistration reg : allRegistrations) {
                    log.info("报名记录: ID={}, 审核状态={}, 状态={}", reg.getId(), reg.getAuditStatus(), reg.getStatus());
                }
                return false;
            }
            
            // 2. 查询已存在的检录记录，避免重复创建
            LambdaQueryWrapper<EventCheckin> checkinWrapper = new LambdaQueryWrapper<>();
            checkinWrapper.eq(EventCheckin::getEventId, eventId);
            List<Long> existingRegistrationIds = this.list(checkinWrapper)
                .stream()
                .map(EventCheckin::getRegistrationId)
                .toList();
            
            // 3. 过滤掉已存在检录记录的报名
            List<EventRegistration> newRegistrations = registrations.stream()
                .filter(reg -> !existingRegistrationIds.contains(reg.getId()))
                .toList();
            
            if (newRegistrations.isEmpty()) {
                log.info("项目 {} 的所有报名记录都已创建检录记录", eventId);
                return true;
            }
            
            // 4. 创建检录记录列表
            List<EventCheckin> checkinList = new ArrayList<>();
            for (EventRegistration registration : newRegistrations) {
                // 获取运动员信息
                Athlete athlete = athleteService.getById(registration.getAthleteId());
                if (athlete == null) {
                    log.warn("运动员 {} 不存在，跳过创建检录记录", registration.getAthleteId());
                    continue;
                }
                
                EventCheckin checkin = new EventCheckin();
                checkin.setEventId(eventId);
                checkin.setRegistrationId(registration.getId());
                checkin.setAthleteId(registration.getAthleteId());
                checkin.setAthleteName(athlete.getRealName());
                checkin.setStudentNumber(athlete.getStudentNumber());
                checkin.setRaceNumber(registration.getRegistrationNumber());
                checkin.setCheckinStatus(0); // 未检录
                
                checkinList.add(checkin);
            }
            
            // 5. 批量保存检录记录
            if (!checkinList.isEmpty()) {
                boolean success = this.saveBatch(checkinList);
                if (success) {
                    log.info("为比赛项目 {} 创建了 {} 条检录记录", eventId, checkinList.size());
                    return true;
                }
            }
            
            return false;
        } catch (Exception e) {
            log.error("创建检录记录失败", e);
            return false;
        }
    }

    /**
     * 为单个报名记录创建检录记录
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean createCheckinRecordForRegistration(EventRegistration registration) {
        try {
            log.info("为报名记录 {} 创建检录记录", registration.getId());
            
            // 检查是否已存在检录记录
            LambdaQueryWrapper<EventCheckin> checkinWrapper = new LambdaQueryWrapper<>();
            checkinWrapper.eq(EventCheckin::getRegistrationId, registration.getId());
            long existingCount = this.count(checkinWrapper);
            
            if (existingCount > 0) {
                log.info("报名记录 {} 已存在检录记录，跳过创建", registration.getId());
                return true;
            }
            
            // 获取运动员信息
            Athlete athlete = athleteService.getById(registration.getAthleteId());
            if (athlete == null) {
                log.warn("运动员 {} 不存在，无法创建检录记录", registration.getAthleteId());
                return false;
            }
            
            // 创建检录记录
            EventCheckin checkin = new EventCheckin();
            checkin.setEventId(registration.getEventId());
            checkin.setRegistrationId(registration.getId());
            checkin.setAthleteId(registration.getAthleteId());
            checkin.setAthleteName(athlete.getRealName());
            checkin.setStudentNumber(athlete.getStudentNumber());
            checkin.setRaceNumber(registration.getRegistrationNumber());
            checkin.setCheckinStatus(0); // 未检录
            
            boolean success = this.save(checkin);
            if (success) {
                log.info("为报名记录 {} 创建检录记录成功", registration.getId());
            }
            
            return success;
        } catch (Exception e) {
            log.error("为报名记录 {} 创建检录记录失败", registration.getId(), e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean checkinAthlete(EventCheckinDTO dto, String operator) {
        try {
            // 查找检录记录
            LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(EventCheckin::getEventId, dto.getEventId())
                   .eq(EventCheckin::getAthleteId, dto.getAthleteId());
            
            EventCheckin checkin = this.getOne(wrapper);
            if (checkin == null) {
                log.error("检录记录不存在: eventId={}, athleteId={}", dto.getEventId(), dto.getAthleteId());
                return false;
            }

            // 更新检录状态
            checkin.setCheckinStatus(1); // 已检录
            checkin.setCheckinTime(LocalDateTime.now());
            checkin.setCheckinOperator(operator);
            
            // 处理签名数据
            checkin.setSignatureImageUrl(dto.getSignatureImageUrl());
            
            checkin.setNotes(dto.getNotes());

            boolean result = this.updateById(checkin);
            
            if (result) {
                log.info("运动员检录成功: eventId={}, athleteId={}, operator={}", 
                        dto.getEventId(), dto.getAthleteId(), operator);
            }
            
            return result;
        } catch (Exception e) {
            log.error("运动员检录失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchCheckin(List<Long> checkinIds, String operator) {
        try {
            for (Long checkinId : checkinIds) {
                EventCheckin checkin = this.getById(checkinId);
                if (checkin != null && checkin.getCheckinStatus() == 0) {
                    checkin.setCheckinStatus(1);
                    checkin.setCheckinTime(LocalDateTime.now());
                    checkin.setCheckinOperator(operator);
                    this.updateById(checkin);
                }
            }
            log.info("批量检录成功: count={}, operator={}", checkinIds.size(), operator);
            return true;
        } catch (Exception e) {
            log.error("批量检录失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAbsent(Long checkinId, String operator, String notes) {
        try {
            EventCheckin checkin = this.getById(checkinId);
            if (checkin == null) {
                return false;
            }

            checkin.setCheckinStatus(2); // 缺席
            checkin.setCheckinTime(LocalDateTime.now());
            checkin.setCheckinOperator(operator);
            checkin.setNotes(notes);

            boolean result = this.updateById(checkin);
            
            if (result) {
                log.info("标记运动员缺席: checkinId={}, operator={}", checkinId, operator);
            }
            
            return result;
        } catch (Exception e) {
            log.error("标记缺席失败", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelCheckin(Long checkinId, String operator) {
        try {
            EventCheckin checkin = this.getById(checkinId);
            if (checkin == null) {
                return false;
            }

            checkin.setCheckinStatus(0); // 未检录
            checkin.setCheckinTime(null);
            checkin.setCheckinOperator(null);
            checkin.setSignatureImageUrl(null);
            checkin.setNotes(operator + " 取消检录");

            boolean result = this.updateById(checkin);
            
            if (result) {
                log.info("取消检录成功: checkinId={}, operator={}", checkinId, operator);
            }
            
            return result;
        } catch (Exception e) {
            log.error("取消检录失败", e);
            return false;
        }
    }

    @Override
    public Map<String, Object> getCheckinStatistics(Long eventId) {
        // 查询统计数据
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventCheckin::getEventId, eventId);
        
        List<EventCheckin> checkins = this.list(wrapper);
        
        Map<String, Object> statistics = new HashMap<>();
        int totalCount = checkins.size();
        int checkedCount = (int) checkins.stream().filter(c -> c.getCheckinStatus() == 1).count();
        int uncheckedCount = (int) checkins.stream().filter(c -> c.getCheckinStatus() == 0).count();
        int absentCount = (int) checkins.stream().filter(c -> c.getCheckinStatus() == 2).count();
        
        statistics.put("totalCount", totalCount);
        statistics.put("checkedCount", checkedCount);
        statistics.put("uncheckedCount", uncheckedCount);
        statistics.put("absentCount", absentCount);
        statistics.put("checkinRate", totalCount > 0 ? (double) checkedCount / totalCount * 100 : 0);
        
        return statistics;
    }

    @Override
    public List<EventCheckinVO> getUncheckedAthletes(Long eventId) {
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventCheckin::getEventId, eventId)
               .eq(EventCheckin::getCheckinStatus, 0) // 未检录
               .orderBy(true, true, EventCheckin::getRaceNumber, EventCheckin::getStudentNumber);
        
        List<EventCheckin> uncheckedList = this.list(wrapper);
        return uncheckedList.stream().map(this::convertToVO).toList();
    }

    @Override
    public boolean isAthleteCheckedIn(Long athleteId, Long eventId) {
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventCheckin::getAthleteId, athleteId)
               .eq(EventCheckin::getEventId, eventId)
               .eq(EventCheckin::getCheckinStatus, 1); // 已检录
        
        return this.count(wrapper) > 0;
    }

    @Override
    public EventCheckinVO getCheckinByAthleteAndEvent(Long athleteId, Long eventId) {
        LambdaQueryWrapper<EventCheckin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EventCheckin::getAthleteId, athleteId)
               .eq(EventCheckin::getEventId, eventId);
        
        EventCheckin checkin = this.getOne(wrapper);
        return checkin != null ? convertToVO(checkin) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCheckinRecord(Long checkinId) {
        try {
            boolean result = this.removeById(checkinId);
            if (result) {
                log.info("删除检录记录成功: checkinId={}", checkinId);
            }
            return result;
        } catch (Exception e) {
            log.error("删除检录记录失败", e);
            return false;
        }
    }
    
    /**
     * 将EventCheckin实体转换为EventCheckinVO
     */
    private EventCheckinVO convertToVO(EventCheckin checkin) {
        EventCheckinVO vo = new EventCheckinVO();
        vo.setId(checkin.getId());
        vo.setEventId(checkin.getEventId());
        vo.setRegistrationId(checkin.getRegistrationId());
        vo.setAthleteId(checkin.getAthleteId());
        vo.setAthleteName(checkin.getAthleteName());
        vo.setStudentNumber(checkin.getStudentNumber());
        vo.setRaceNumber(checkin.getRaceNumber());
        vo.setCheckinStatus(checkin.getCheckinStatus());
        vo.setCheckinTime(checkin.getCheckinTime());
        vo.setCheckinOperator(checkin.getCheckinOperator());
        vo.setSignatureImageUrl(checkin.getSignatureImageUrl());
        vo.setNotes(checkin.getNotes());
        vo.setCreateTime(checkin.getCreateTime());
        vo.setUpdateTime(checkin.getUpdateTime());
        
        // 设置状态文本
        String statusText = switch (checkin.getCheckinStatus()) {
            case 0 -> "未检录";
            case 1 -> "已检录";
            case 2 -> "缺席";
            default -> "未知";
        };
        vo.setCheckinStatusText(statusText);
        
        // 设置是否可以录入成绩
        vo.setCanRecordScore(checkin.getCheckinStatus() == 1);
        
        // 加载比赛项目信息
        if (checkin.getEventId() != null) {
            CompetitionEvent event = competitionEventService.getById(checkin.getEventId());
            if (event != null) {
                vo.setEventName(event.getEventName());
                vo.setEventCode(event.getEventCode());
                vo.setCompetitionTime(event.getCompetitionTime());
            }
        }
        
        // 加载运动员详细信息
        if (checkin.getAthleteId() != null) {
            Athlete athlete = athleteService.getById(checkin.getAthleteId());
            if (athlete != null) {
                vo.setDepartment(athlete.getDepartment());
                vo.setClassName(athlete.getClassName());
            }
        }
        
        return vo;
    }
}
